package com.qk.management.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.qk.common.constant.CacheConstants;
import com.qk.domain.business.BusinessCountDO;
import com.qk.domain.clue.ClueCountDO;
import com.qk.management.aop.anno.Cacheable;
import com.qk.management.mapper.BusinessMapper;
import com.qk.management.mapper.ClueMapper;
import com.qk.management.service.ReportOverviewService;
import com.qk.vo.portal.PortalVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 *
 * @author MrZhao
 * @created 2025-10-15 14:53
 * @description 首页数据概览业务层实现类
 *
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class ReportOverviewServiceImpl implements ReportOverviewService {

    @Autowired
    private ClueMapper clueMapper;
    @Autowired
    private BusinessMapper businessMapper;
    @Autowired
    private StringRedisTemplate redisClient;

    // 使用缓存基本原则，使用缓存不能影响正常的业务逻辑！Java基础的try...catch...

    // 利用Reis优化程序
    // 1. 选择数据类型  选择使用 string类型
    // 2. 操作步骤
    // 2.1 先查询缓存
    // 2.2 如果缓存命中直接返回
    // 2.3 未命中查询数据库，添加数据到缓存
    // 2.4 返回数据
    // 绘制流程图
    // 定义Redis缓存key的前缀，使用技巧基于：号连接！
    private static final String CACHE_PORTAL_KEY_PREFIX = "qk:portal:";

    @Override
    public PortalVO reportOverviewWitchCache() {
        //1. 定义缓存key
        String redisKey = CACHE_PORTAL_KEY_PREFIX + "reportOverview";
        //2. 查询缓存
        String jsonStr = null;
        try {
            jsonStr = redisClient.opsForValue().get(redisKey);
            // 2.1 判断缓存是否命中
            if (ObjectUtil.isNotEmpty(jsonStr)) {
                // 命中 jsonStr 转成Java对象
                PortalVO vo = JSONUtil.toBean(jsonStr, PortalVO.class);
                return vo;
            }
        } catch (Exception e) {
            log.error("查询缓存异常", e);
        }
        // 2.2 未命中查询数据库
        // 统计线索相关数据
        ClueCountDO clueCountDO = clueMapper.selectCountClue();
        // 统计商机相关数据
        BusinessCountDO businessCountDO = businessMapper.selectCountBusiness();
        // 线索数据封装到VO
        PortalVO vo = BeanUtil.copyProperties(clueCountDO, PortalVO.class);
        // 商机数据封装到VO
        BeanUtil.copyProperties(businessCountDO, vo);
        // 3. 添加数据到缓存
        try {
            String json = JSONUtil.toJsonStr(vo);
            redisClient.opsForValue().set(redisKey, json);
        } catch (Exception e) {
            log.error("添加缓存异常", e);
        }
        return vo;
    }

    @Cacheable(
            keyPrefix = CacheConstants.CACHE_PORTAL_KEY_PREFIX,
            expireTime = 24*60L,
            expireTimeUnit = TimeUnit.MINUTES
    )
    @Override
    public PortalVO reportOverview() {
        // 统计线索相关数据
        ClueCountDO clueCountDO = clueMapper.selectCountClue();
        // 统计商机相关数据
        BusinessCountDO businessCountDO = businessMapper.selectCountBusiness();
        // 线索数据封装到VO
        PortalVO vo = BeanUtil.copyProperties(clueCountDO, PortalVO.class);
        // 商机数据封装到VO
        BeanUtil.copyProperties(businessCountDO, vo);
        return vo;
    }
}
